package com.sixfoot.server;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.springframework.stereotype.Component;

import com.google.protobuf.ExtensionRegistry;
import com.sixfoot.App;
import com.sixfoot.foundation.utils.SystemErrorCodes;
import com.sixfoot.hrv.codec.protobuf.ChangePasswordReqProto;
import com.sixfoot.hrv.codec.protobuf.DataEpReqProto;
import com.sixfoot.hrv.codec.protobuf.DataHrvReqProto;
import com.sixfoot.hrv.codec.protobuf.DataIbiReqProto;
import com.sixfoot.hrv.codec.protobuf.DataPpgReqProto;
import com.sixfoot.hrv.codec.protobuf.GetResourceListReqProto;
import com.sixfoot.hrv.codec.protobuf.LoginReqProto;
import com.sixfoot.hrv.codec.protobuf.MarkScaleReqProto;
import com.sixfoot.hrv.codec.protobuf.RequestProto;
import com.sixfoot.hrv.codec.protobuf.ResponseProto;
import com.sixfoot.hrv.codec.protobuf.ScaleListReqProto;
import com.sixfoot.hrv.codec.protobuf.ScaleReqProto;
import com.sixfoot.hrv.codec.protobuf.StartScaleReqProto;
import com.sixfoot.hrv.codec.protobuf.StopScaleReqProto;
import com.sixfoot.hrv.codec.protobuf.UpdateUserInfoReqProto;
import com.sixfoot.server.handler.ReqHandler;
import com.sixfoot.service.ServerManager;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

@Component("server")
public class Server {
//	@Autowired
//	private UserService userService;
	
	public void start(int port) throws Exception {
//		userService.updatePassword("zhangsan", "123");
		// 配置服务端的NIO线程组
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup)
				.channel(NioServerSocketChannel.class)
				.option(ChannelOption.SO_BACKLOG, 100)
				.handler(new LoggingHandler(LogLevel.INFO))
				.childHandler(new ChannelInitializer<SocketChannel>() {

					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						// 扩展注册
						ExtensionRegistry registry = ExtensionRegistry.newInstance();
						StartScaleReqProto.registerAllExtensions(registry);
						StopScaleReqProto.registerAllExtensions(registry);
						StopScaleReqProto.registerAllExtensions(registry);
						DataPpgReqProto.registerAllExtensions(registry);
						DataEpReqProto.registerAllExtensions(registry);
						DataHrvReqProto.registerAllExtensions(registry);
						DataIbiReqProto.registerAllExtensions(registry);
						MarkScaleReqProto.registerAllExtensions(registry);
						ChangePasswordReqProto.registerAllExtensions(registry);
						LoginReqProto.registerAllExtensions(registry);
						GetResourceListReqProto.registerAllExtensions(registry);
						UpdateUserInfoReqProto.registerAllExtensions(registry);
						ScaleReqProto.registerAllExtensions(registry);
						ScaleListReqProto.registerAllExtensions(registry);
						RequestProto.registerAllExtensions(registry);
						
						ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
						ch.pipeline().addLast(new ProtobufDecoder(RequestProto.Request.getDefaultInstance(), registry));
						ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
						ch.pipeline().addLast(new ProtobufEncoder());
//						ch.pipeline().addLast(new LoginReqHandler());
						ch.pipeline().addLast(App.context.getBean("reqHandler", ReqHandler.class));
					}

				});
			

			// 绑定端口，同步等待成功
			ChannelFuture f = b.bind(port).sync();
			Channel channel = f.channel();
			String line = null;
			// 不断读取键盘输入
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			while ((line = br.readLine()) != null) {
				if (line.equals("hello")) {
					ResponseProto.Response.Builder resultBuilder = ResponseProto.Response.newBuilder();
					
					ResponseProto.RespFailed.Builder failedBuilder = ResponseProto.RespFailed.newBuilder();
					failedBuilder.setCode(SystemErrorCodes.UNLOGIN.getCode());
					failedBuilder.setError(SystemErrorCodes.UNLOGIN.getError());
					failedBuilder.setErrorDescription("测试一下主动发送");
					ResponseProto.RespFailed respFailed = failedBuilder.build();
					
					resultBuilder.setStatus(ResponseProto.Response.Status.ERROR);
					resultBuilder.setExtension(ResponseProto.RespFailed.respfailed, respFailed);
					ServerManager.sendPacketToAllUsers(resultBuilder.build());
				}
			}

			// 等待服务器监听端口关闭
			f.channel().closeFuture().sync();

		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
	}
}
